using System;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace MediaOwl.Common.ControlTemplates
{
    [TemplateVisualState(Name = "Closed", GroupName = "WindowStates")]
    [TemplateVisualState(Name = "Open", GroupName = "WindowStates")]
    public class DialogControl : ContentControl
    {
        #region Fields

        private bool isClosing;

        /// <summary>
        /// The name of the Root template part.
        /// </summary>
        private const string PartRoot = "Root";

        /// <summary>
        /// The name of the WindowStates VSM group.
        /// </summary>
        private const string VsmGroupWindow = "WindowStates";

        /// <summary>
        /// The name of the Closing VSM state.
        /// </summary>
        private const string VsmStateStateClosed = "Closed";

        /// <summary>
        /// The name of the Opening VSM state.
        /// </summary>
        private const string VsmStateStateOpen = "Open";



        /// <summary>
        /// Private accessor for the Closing storyboard.
        /// </summary>
        private Storyboard closed;

        /// <summary>
        /// Private accessor for the Opened storyboard.
        /// </summary>
        private Storyboard opened;

        /// <summary>
        /// Private accessor for the Root of the window.
        /// </summary>
        private FrameworkElement root;

        #endregion

        #region ctor

        public DialogControl()
        {
            isClosing = false;
            DefaultStyleKey = typeof(DialogControl);
        }

        #endregion

        #region DependencyProperties for Logic

        #region TitleProperty
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
            "Title",
            typeof(string),
            typeof(DialogControl),
            new PropertyMetadata("DialogTitle"));

        [Category("Common Properties"), Description("The Title of the Dialog")]
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set
            {
                SetValue(TitleProperty, value);
            }
        }
        #endregion

        #endregion

        #region DependencyProperties for Style

        #region TitleBackgroundProperty
        public static readonly DependencyProperty TitleBackgroundProperty = DependencyProperty.Register(
            "TitleBackground",
            typeof(Brush),
            typeof(DialogControl),
            new PropertyMetadata(new SolidColorBrush(Colors.Gray)));

        [Category("Brushes"), Description("The Title's Background")]
        public Brush TitleBackground
        {
            get { return (Brush)GetValue(TitleBackgroundProperty); }
            set { SetValue(TitleBackgroundProperty, value); }
        }
        #endregion

        #region TitleForegroundProperty
        public static readonly DependencyProperty TitleForegroundProperty = DependencyProperty.Register(
            "TitleForeground",
            typeof(Brush),
            typeof(DialogControl),
            new PropertyMetadata(new SolidColorBrush(Colors.White)));

        [Category("Brushes"), Description("The Title's Foreground")]
        public Brush TitleForeground
        {
            get { return (Brush)GetValue(TitleForegroundProperty); }
            set { SetValue(TitleForegroundProperty, value); }
        }
        #endregion

        #region TitleHeightProperty

        public static readonly DependencyProperty TitleHeightProperty = DependencyProperty.Register(
            "TitleHeight",
            typeof(double),
            typeof(DialogControl),
            new PropertyMetadata(60d));

        [Category("Layout"), Description("The Title's Height")]
        public double TitleHeight
        {
            get { return (double)GetValue(TitleHeightProperty); }
            set { SetValue(TitleHeightProperty, value); }
        }
        #endregion

        #region ScreenCornersProperty
        public static readonly DependencyProperty ScreenCornersProperty = DependencyProperty.Register(
            "ScreenCorners",
            typeof(CornerRadius),
            typeof(DialogControl),
            new PropertyMetadata(new CornerRadius(5d, 5d, 5d, 5d)));

        [Category("Layout"), Description("The CornerRadius of the Screen")]
        public CornerRadius ScreenCorners
        {
            get { return (CornerRadius)GetValue(ScreenCornersProperty); }
            set { SetValue(ScreenCornersProperty, value); }
        }
        #endregion

        #endregion

        #region Methods



        /// <summary>
        /// Subscribes to events that are on the storyboards. 
        /// Unsubscribing from these events happen in the event handlers individually.
        /// </summary>
        private void SubscribeToStoryBoardEvents()
        {
            if (closed != null)
            {
                closed.Completed += ClosingCompleted;
            }

            if (opened != null)
            {
                opened.Completed += OpeningCompleted;
            }
        }

        /// <summary>
        /// Executed when the Closing storyboard ends.
        /// </summary>
        /// <param name="sender">Sender object.</param>
        /// <param name="e">Event args.</param>
        private void ClosingCompleted(object sender, EventArgs e)
        {
            Closed(this, new EventArgs());
            if (closed != null)
            {
                closed.Completed -= ClosingCompleted;
            }
            
        }

        /// <summary>
        /// Executed when the opening storyboard finishes.
        /// </summary>
        /// <param name="sender">Sender object.</param>
        /// <param name="e">Event args.</param>
        private void OpeningCompleted(object sender, EventArgs e)
        {
            if (opened != null)
            {
                opened.Completed -= OpeningCompleted;
            }
        }

        public void Close()
        {
            Closing(this, new CancelEventArgs(false));
            isClosing = true;
            try
            {
                ChangeVisualState();
            }
            finally
            {
                isClosing = false;
            }
        }

        /// <summary>
        /// Changes the visual state of the ChildWindow.
        /// </summary>
        private void ChangeVisualState(bool useTransitions = true)
        {
            VisualStateManager.GoToState(this
                , isClosing ? VsmStateStateClosed : VsmStateStateOpen
                , useTransitions);
        }

        public override void OnApplyTemplate()
        {
            if (closed != null)
            {
                closed.Completed -= ClosingCompleted;
            }

            if (opened != null)
            {
                opened.Completed -= OpeningCompleted;
            }

            root = GetTemplateChild(PartRoot) as FrameworkElement;

            if (root != null)
            {
                IList groups = VisualStateManager.GetVisualStateGroups(root);

                IList states =
                    (from VisualStateGroup vsg in groups where vsg.Name == VsmGroupWindow select vsg.States).FirstOrDefault();

                if (states != null)
                {
                    foreach (VisualState state in states)
                    {
                        if (state.Name == VsmStateStateClosed)
                            closed = state.Storyboard;

                        if (state.Name == VsmStateStateOpen)
                            opened = state.Storyboard;
                    }
                }

            }
            SubscribeToStoryBoardEvents();

            //isClosing = true;
            //ChangeVisualState(false);
            isClosing = false;
            base.OnApplyTemplate();
            ChangeVisualState();
        }

        

        #endregion

        public event EventHandler Closed = delegate { };

        public event EventHandler<CancelEventArgs> Closing = delegate { };
    }
}